//
// Created by QU on 2024/4/9.
//

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;


void check_function(const string &s, int &counter);

void check_function_single(const string &s);

void printContent(ostream &os, const string &s, int &counter, int plusVal);

int a = 100;

int main(int argc, [[maybe_unused]] const char *argv[]) {

    int b = 100;
    vector<string> vs{"aquawius", "this", "hahaha", "lambda", "testing", "returned", "type", "functionly"};

    /*
    // 因为b属于main函数的局部变量, 需要使用捕获变量才能修改.
    for_each(vs.cbegin(), vs.cend(), [&b](auto str){
        cout << str << " ";
        cout << b << endl;
        b++;
    });

    // 如果a是全局变量
    for_each(vs.cbegin(), vs.cend(), [](auto str){
        static int &a = ::a;
        cout << str << " ";
        cout << a << endl;
        a++;
    });
    */

    // lambda有捕获列表, 但是如果你想写一个带有两个参数函数在这里, for_each函数模板就不能调用这个函数,
    // 引出std::bind(), 在头文件functional中

    //  调用bind的一般形式为：
    // auto newCallable = bind(callable, arg_list);
    // 其中，newCallable本身是一个可调用对象，arg_list是一个逗号分隔的参数列表，对应给定的callable的参数。
    // 即，当我们调用newCallable时，newCallable会调用callable，并传递给它arg_list中的参数。

    // arg_list中的参数可能包含形如_n的名字，其中n是一个整数。这些参数是“占位符”

//    auto improved_check_function = bind(check_function, _1, a);


    auto improved_check_function = bind(check_function, std::placeholders::_1, b);
//    这里clang希望更改成lambda表达式..............
//    auto improved_check_function = [b](auto && PH1) { return check_function(std::forward<decltype(PH1)>(PH1), b); };

    for_each(vs.begin(), vs.end(), check_function_single);
    cout << endl;

    cout << "----------------------------------------------------------" << endl;
    for_each(vs.begin(), vs.end(), improved_check_function);
    cout << "----------------------------------------------------------" << endl;

    auto bind_print_content = std::bind(printContent, std::ref(cout), std::placeholders::_1, a, 4);
    for_each(vs.begin(), vs.end(), bind_print_content);


    return 0;

}

void check_function(const string &s, int &counter) {
    cout << s << " ";
    cout << counter++ << endl;
}

void check_function_single(const string &s) {
    cout << s << " ";
}

void printContent(ostream &os, const string &s, int &counter, int plusVal) {
    os << s << " ";
    os << (counter += plusVal) << endl;
}
